package com.jiangyg.mall.gateway.support.route;

import com.jiangyg.mall.core.utils.Logger;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.http.server.PathContainer;
import org.springframework.stereotype.Component;
import org.springframework.web.util.pattern.PathPatternParser;

import java.util.List;
import java.util.Map;

/**
 * 类描述：根据网关配置解析出真实的请求地址
 *
 * @author jiangyg
 * @date 2022-09-05
 */
@Slf4j
@Component
public class RouteHandlerImpl implements RouteHandler {

    /**
     * 网关路由属性配置
     */
    private final GatewayProperties properties;

    @Autowired
    public RouteHandlerImpl(GatewayProperties properties) {
        this.properties = properties;
    }

    @Override
    public String realPath(String path) {
        // 路径为空则不处理
        if (StringUtils.isBlank(path)) {
            return path;
        }
        // 遍历路由规则，进行处理
        for (RouteDefinition route : properties.getRoutes()) {
            final List<PredicateDefinition> predicates = route.getPredicates();
            for (PredicateDefinition predicate : predicates) {
                final String key0 = NameUtils.generateName(0);
                // 如果正则不匹配则跳出本次循环
                final String pvalue = predicate.getArgs().get(key0);
                if (!new PathPatternParser().parse(pvalue).matches(PathContainer.parsePath(path))) {
                    Logger.debug(log, () -> String.format("网关路径[%s]不符合路由断言[%s][%s]规则条件！", path, predicate.getName(), pvalue));
                    continue;
                }
                // 如果断言匹配成功则根据重写规则，获取真实路径
                final List<FilterDefinition> filters = route.getFilters();
                for (FilterDefinition filter : filters) {
                    final Map<String, String> fargs = filter.getArgs();
                    final String iregex = fargs.get(key0);
                    final String replacement = fargs.get(NameUtils.generateName(1)).replace("$\\", "$");
                    final String fpath = path.replaceAll(iregex, replacement);
                    Logger.debug(log, () -> String.format("网关路径[%s]经过[%s][%s]规则处理结果：[%s]！", path, filter.getName(), iregex, fpath));
                    return fpath;
                }
            }
        }
        return path;
    }

}
